#include "Comm.hpp"
#include "Log.hpp"

#include <cstring>
#include <cerrno>
#include <unistd.h>
// #include <stdio.h> //getline 用C++的

#include <iostream>
#include <string>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
const int RETRYTIMES = 5;
void Usage(const std::string &proc)
{
    std::cout << "格式：" << proc << " serverip serverport" << std::endl;
}

int VisitServer(const std::string& serverip, uint16_t serverport, int& sockfd)
{
    // 1.创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        lg.LogMessage(Fatal, "sockfd create falied, errno:%d, %s\n", errno, strerror(errno));
        return sockfd_err;
    }
    lg.LogMessage(Debug, "sockfd create succsee\n");

    // 2.1填写服务器信息
    struct sockaddr_in server;
    memset(&server, 0, sizeof server);
    server.sin_family = AF_INET;
    inet_pton(AF_INET, (const char *)serverip.c_str(), &server.sin_addr);
    server.sin_port = htons(serverport);
    // 2.2connect建立链接
    int ok = connect(sockfd, (struct sockaddr *)&server, sizeof server);
    if (ok == -1)
    {
        lg.LogMessage(Warning, "connect falied, errno:%d, %s\n", errno, strerror(errno));
        return connect_err;
    }
    lg.LogMessage(Debug, "connect success\n");

    while (true)
    {
        std::cout << "输入内容: \n";
        std::string str;
        getline(std::cin, str);
        if(str == "quit")
            return client_queit;
        int n = write(sockfd, str.c_str(), str.size());
        std::cout << "n" << n << std::endl;
        if (n > 0)
        {
            char buffer[128] = {0}; // 这样的话，末尾添加0可以去掉
            int m = read(sockfd, buffer, sizeof buffer - 1);
            if (m > 0)
            {
                lg.LogMessage(Debug, "m: %d\n", m);
                // buffer[m] = 0;
                std::cout << buffer << std::endl;
                
                // for(int i = 0; i < m; i++)
                //     std::cout << i << ": "<<buffer[i] << std::endl;
            }
            else if (m == 0)
            {
                lg.LogMessage(Warning, "与服务器断开连接, errno: %d, %s\n", errno, strerror(errno));
                break;
            }
            else
            {
                lg.LogMessage(Error, "read错误, errno: %d, %s\n", errno, strerror(errno));
                read_err;
            }
        }
        else
            break;
    }
    return 0;
}
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[1]);
        return usage_err;
    }

    std::string serverip = argv[1];
    uint16_t port = std::stoi(argv[2]);
    int cnt = RETRYTIMES;
    while(cnt > 0)
    {
        int sockfd;
        int ok = VisitServer(serverip, port, sockfd);
        if(ok == client_queit) 
        {
            close(sockfd);
            break;
        }
        else if(ok == connect_err || ok == read_err)
        {
            cnt--;
            std::cout << "connect retry...times:" << RETRYTIMES - cnt << std::endl;
            sleep(1);
        }
        else
            cnt = RETRYTIMES;
        close(sockfd);
    }
    if(cnt == 0)
        std::cout << "服务器断开" << std::endl;
    else std::cout << "正常退出" << std::endl;
    return 0;
}